package com.eeds.service.upload.impl;

import com.eeds.common.model.RespEnum;
import com.eeds.common.table.SysFilesEntity;
import com.eeds.dao.SysFilesDao;
import com.eeds.date.DateUtil;
import com.eeds.exception.ServerException;
import com.eeds.model.upload.req.ReqUploadBase64FileVO;
import com.eeds.model.upload.req.ReqUploadFileVO;
import com.eeds.model.upload.res.ResUploadFileVO;
import com.eeds.service.upload.UploadService;
import com.eeds.servlet.HttpServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;

@Service
@Slf4j
public class UploadServiceImpl implements UploadService {

    @Value("${file.base.path}")
    private String fileBasePath;

    @Autowired
    private SysFilesDao sysFilesDao;

    /**
     * 上传文件
     *
     * @param reqUploadFileVO
     * @return
     */
    @Override
    public ResUploadFileVO uploadFile(ReqUploadFileVO reqUploadFileVO) {
        MultipartFile file = reqUploadFileVO.getUploadfile();
        if (file.isEmpty()) {
            throw new ServerException(RespEnum.FILE_IS_NULL);
        }
        // 获取文件名
        String fileName = file.getOriginalFilename();
        if(log.isInfoEnabled()) {
            log.info("上传的文件名为：" + fileName);
        }
        // 获取文件的后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        if(log.isInfoEnabled()) {
            log.info("上传的后缀名为：" + suffixName);
        }

        // 新文件名称
        String newFileName = UUID.randomUUID() + suffixName;
        if(log.isInfoEnabled()) {
            log.info("新文件名称名为：" + newFileName);
        }

        File dest = new File(fileBasePath + newFileName);
        // 检测是否存在目录
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }

        try {
            file.transferTo(dest);
            //return "上传成功";
        }  catch (IOException e) {
            if(log.isErrorEnabled()){
                log.error("文件上传失败",e);
            }
            throw new ServerException(RespEnum.UPLOAD_FILE_ERROR);
        }
        SysFilesEntity sysFilesEntity = new SysFilesEntity();
        sysFilesEntity.setFileName(fileName);
        sysFilesEntity.setCreateDate(DateUtil.nowDate());
        sysFilesEntity.setFilePath(dest.getPath());
        sysFilesEntity.setIdxUserBaseInfo(reqUploadFileVO.getUserId());
        sysFilesEntity.setSuffixName(suffixName);
        sysFilesEntity.setIp(HttpServletUtil.getRequestIp());
        sysFilesEntity.setStatus(0);
        sysFilesDao.insert(sysFilesEntity);

        ResUploadFileVO resUploadFileVO  = new ResUploadFileVO();
        resUploadFileVO.setFileName(sysFilesEntity.getFileName());
        resUploadFileVO.setFilePath(sysFilesEntity.getFilePath());
        resUploadFileVO.setSuffixName(sysFilesEntity.getSuffixName());
        resUploadFileVO.setIdSysFiles(sysFilesEntity.getIdSysFiles());
        return resUploadFileVO;
    }

    /**
     * 修改文件状态
     *
     * @param fileId
     * @return
     */
    @Override
    public Integer updateFileStatus(Long fileId) {
        SysFilesEntity sysFilesEntity = new SysFilesEntity();
        sysFilesEntity.setIdSysFiles(fileId);
        sysFilesEntity.setStatus(1);
        sysFilesDao.updateById(sysFilesEntity);
        return 1;
    }

    @Override
    @Transactional
    public ResUploadFileVO uploadBase64File(ReqUploadBase64FileVO reqUploadBase64FileVO) {


        String suffixName = ".png";

        // 新文件名称
        String newFileName = UUID.randomUUID() + suffixName;

        File dest = new File(fileBasePath + newFileName);
        // 检测是否存在目录
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }

        //使用工具类 提供的方法 generateImage(String imgStr, String path)  上传图片并保存
        if(generateImage(reqUploadBase64FileVO.getImgMechanics(),dest.getPath())) {
            SysFilesEntity sysFilesEntity = new SysFilesEntity();
            sysFilesEntity.setFileName(newFileName);
            sysFilesEntity.setCreateDate(DateUtil.nowDate());
            sysFilesEntity.setFilePath(dest.getPath());
            sysFilesEntity.setIdxUserBaseInfo(reqUploadBase64FileVO.getUserId());
            sysFilesEntity.setSuffixName(suffixName);
            sysFilesEntity.setIp(HttpServletUtil.getRequestIp());
            sysFilesEntity.setStatus(0);
            sysFilesDao.insert(sysFilesEntity);

            ResUploadFileVO resUploadFileVO  = new ResUploadFileVO();
            resUploadFileVO.setFileName(sysFilesEntity.getFileName());
            resUploadFileVO.setFilePath(sysFilesEntity.getFilePath());
            resUploadFileVO.setSuffixName(sysFilesEntity.getSuffixName());
            resUploadFileVO.setIdSysFiles(sysFilesEntity.getIdSysFiles());
            return resUploadFileVO;

        }else{
            throw new ServerException(RespEnum.UPLOAD_FILE_ERROR);
        }




    }

    public static boolean generateImage(String imgStr, String path) {
        String  base64Type = "data:image/png;base64,";
        if (imgStr == null ||  imgStr.length()<base64Type.length()) {//接收的base64代码应该小于base64的头部内容
            return false;
        }
        imgStr = imgStr.substring(base64Type.length());
        BASE64Decoder decoder = new BASE64Decoder();
        OutputStream out = null;
        try {

            // 解密
            byte[] b = decoder.decodeBuffer(imgStr);
            // 处理数据
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            out= new FileOutputStream(path);
            out.write(b);
            out.flush();
            return true;
        } catch (Exception e) {
            return false;
        }finally {
            if(out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
